using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Runtime.Serialization;

namespace net.notdot.Attercop
{
    [Serializable()]
    public class HelloMessage : Message, UdpMessage
    {
        public readonly byte[] PublicKey;
        public readonly string Nick = "";
        public readonly long TotalShared;

        static HelloMessage() { ClientInstance.AddMessageHandler<HelloMessage>(); }

        public HelloMessage(MessageAddressing addressing, Peer p) : base(addressing)
        {
            PublicKey = p.PublicKey.ExportCspBlob(false);

            Nick = p.Nick;
            TotalShared = p.TotalShared;
        }

        protected HelloMessage(MessageReader reader)
            : base(reader)
        {
            reader.BeginRegion();
            reader.ReadByte();  //Version
            this.PublicKey = reader.ReadBytes();
            this.Nick = reader.ReadString();
            this.TotalShared = reader.ReadInt64();
            reader.EndRegion();
        }

        public override void Serialize(MessageWriter writer)
        {
            base.Serialize(writer);

            writer.BeginRegion();
            writer.Write((byte)0);  //Version
            writer.Write(this.PublicKey);
            writer.Write(this.Nick);
            writer.Write(this.TotalShared);
            writer.EndRegion();
        }

        public virtual void Handle(ClientInstance c)
        {
            Peer p;

            lock (c.Peers)
            {
                if (!c.Peers.ContainsKey(this.Addressing.From))
                {
                    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                    rsa.ImportCspBlob(PublicKey);

                    //New peer
                    p = new Peer(this.Addressing.From, rsa, Nick, TotalShared);
                    c.Peers.Add(this.Addressing.From, p);
                }
                else
                {
                    //Existing peer
                    p = c.Peers[this.Addressing.From];
                }
            }

            //Ping them if we haven't completed a handshake with them
            if (!p.Introduced)
            {
                PingMessage ping = new PingMessage(new MessageAddressing(c.LocalPeer.Address, this.Addressing.From), c.LocalPeer);
                c.pings.Add(ping.PingId, ping);
                c.SendMessage(ping);
            }

            p.TotalShared = this.TotalShared;
            //TODO: Trigger a nick change event if the nick has changed
            p.Nick = this.Nick;
        }
    }
}
